/******************************************************************************
*	types.h
*	 by Alex Chadwick
*
*	A light weight implementation of the USB protocol stack fit for a simple
*	driver.
*
*	types.h contains definitions of standardised types used ubiquitously.
******************************************************************************/
#ifndef _TYPES_H
#define _TYPES_H

// "attribute"s are compiler specific
#define STRUCTPACK  __attribute__ ((__packed__))
#define ALIGN4      __attribute__ ((aligned(4)))
#define ALIGN8      __attribute__ ((aligned(8)))

// Basic variable types
typedef  unsigned  char       u8;   // Unsigned  8-bit
typedef  unsigned  short      u16;  // Unsigned 16-bit
typedef  unsigned  int        u32;  // Unsigned 32-bit
typedef  unsigned  long long  u64;  // Unsigned 64-bit

typedef  signed    char       s8;   // Signed  8-bit
typedef  signed    short      s16;  // Signed 16-bit
typedef  signed    int        s32;  // Signed 32-bit
typedef  signed    long long  s64;  // Signed 64-bit

// 1-bit truth value
typedef
	enum {
		false = 0,
		true  = 1,
	}
bool;

#define  TRUE   (1)
#define  FALSE  (0)

// Result of a method call
typedef
	enum {
		OK                  =   0,  // Success
		ErrorGeneral        =  -1,  // Undisclosed failure
		ErrorArgument       =  -2,  // Bad input
		ErrorRetry          =  -3,  // Temporary error; retry ...caller should limit retry attempts
		ErrorDevice         =  -4,  // Permanent error; enact hardware reset & retry
		ErrorIncompatible   =  -5,  // Detected device is unsupported
		ErrorCompiler       =  -6,  // Compiler configuration error
		ErrorMemory         =  -7,  // Out of memory
		ErrorTimeout        =  -8,  // Timeout waiting for device; retry optional.
		ErrorDisconnected   =  -9,  // Device disconnected during transfer
		ErrorNotImplemented = -10,  // Functionality not (yet) implemented
	}
Result;

// Direction of USB communication (1-bit)
typedef
	enum {
		HostToDevice = 0,
		Out          = 0,
		DeviceToHost = 1,
		In           = 1,
	}
UsbDirection;

// Speed of USB connection (2-bits)
typedef
	enum {
		High = 0,
		Full = 1,
		Low  = 2,
	}
UsbSpeed;

// USB Transfer type (2-bits)
typedef
	enum {
		Control     = 0,
		Isochronous = 1,
		Bulk        = 2,
		Interrupt   = 3,
	}
UsbTransfer;

// USB Transaction size (2-bits)
typedef
	enum {
		Bits8  = 0,
		Bits16 = 1,
		Bits32 = 2,
		Bits64 = 3,
	}
UsbPacketSize;

// Convert a UsbSpeed to a humaised string
static inline
const char*  SpeedToChar (UsbSpeed speed)
{
	if      (speed == High)  return "480 Mb/s" ;
	else if (speed == Low)   return "1.5 Mb/s" ;
	else if (speed == Full)  return "12 Mb/s" ;
	else                     return "Unknown Mb/s" ;
}

// Convert a bit-size to a size-type
static inline
UsbPacketSize  SizeFromNumber (u32 size)
{
	if      (size <=  8)  return Bits8 ;
	else if (size <= 16)  return Bits16 ;
	else if (size <= 32)  return Bits32 ;
	else                  return Bits64 ;
}

// Convert a size-type to a bit-size
static inline
u32  SizeToNumber (UsbPacketSize size)
{
	if      (size == Bits8 )  return 8 ;
	else if (size == Bits16)  return 16 ;
	else if (size == Bits32)  return 32 ;
	else                      return 64 ;
}

// Return the minimum of two inputs
// The type is supplied so we can ensure only one evaluation of each input
#define Min(x, y, type) \
	({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })

// Return the maximum of two inputs
// The type is supplied so we can ensure only one evaluation of each input
#define Max(x, y, type) \
	({ type __x = (x); type __y = (y); __x < __y ? __y : __x; })

#endif // _TYPES_H
